import { _decorator, AudioSource, director, Node, Prefab } from 'cc'
import { SettingManager } from '../../data/SettingManager'
import { RoundState, ShakerState } from '../../types/StateEnums'
import { DiceUtil } from '../../utils/DiceUtil'
import {
	AnimationUtils,
	ClickBindingOptions,
	GridLayoutUtil,
	PropertyBindingOptions,
	ZAssetManager,
	ZController
} from '../../Zcc'
import { DiceController } from './DiceController'
import { ShakerController } from './ShakerController'

const { ccclass, property } = _decorator

@ccclass('RoundController')
export class RoundController extends ZController {
	/** 晃动动画配置 */
	private static readonly SHAKE_CONFIG = {
		distance: 30, // 晃动距离
		totalTime: 1.0, // 总时长
		shakeCount: 18, // 晃动次数
		duration: {
			start: 0.08, // 起始动画时长
			end: 0.08 // 结束动画时长
		},
		easing: 'quadOut', // 缓动类型
		direction: 'horizontal' // 晃动方向
	} as const

	/** 骰子布局配置 */
	private static readonly DICE_CONFIG = {
		cellWidth: 65,
		cellHeight: 54
	} as const

	protected propertyBindings: Record<string, string | ({ path: string } & PropertyBindingOptions)> = {
		diceSlot: 'shaker-container/dice-slot',
		shakerOrigin: 'shaker-container/shaker-origin',
		shakerTarget: 'shaker-container/shaker-target',
		shakerContainer: 'shaker-container',
		shakerController: { path: 'shaker-container/shaker', component: ShakerController }
	}
	protected clickBindings: Record<string, string | ({ path: string } & ClickBindingOptions)> = {
		onButton: 'ShakeButton'
	}

	private dicePrefab: Prefab = null
	private shakerController: ShakerController = null
	/** 骰子容器节点 */
	private diceSlot: Node = null
	/** 骰盅初始位置节点 */
	private shakerOrigin: Node = null
	/** 骰盅目标位置节点 */
	private shakerTarget: Node = null
	/** 骰盅容器节点 */
	private shakerContainer: Node = null
	/** 骰子组件列表 */
	private diceList: DiceController[] = []
	/** 网格布局工具 */
	private gridLayoutUtil: GridLayoutUtil = null

	/** 骰盅局状态 */
	private roundState: RoundState = RoundState.IDLE
	/** 骰盅状态 */
	private shakeState: ShakerState = ShakerState.CLOSE

	/** 组件加载完成回调 */
	protected onControllerLoad(): void {
		console.log('RoundController onControllerLoad')

		this.dicePrefab = ZAssetManager.instance.getAsset<Prefab>(SettingManager.instance.settings.dice_prefab)

		this.shakerController.setPosRange(this.shakerOrigin.position, this.shakerTarget.position)
		this.initGridLayout()

		this.rollDice(true)

		director.on('onDiceCountChange', this.onDiceCountChange.bind(this))
	}

	/** 初始化网格布局 */
	private initGridLayout(): void {
		const diceCount = SettingManager.instance.settings.dice_num
		this.gridLayoutUtil = new GridLayoutUtil(this.diceSlot, this.dicePrefab, diceCount, RoundController.DICE_CONFIG)
	}

	/** 按钮点击回调 */
	private onButton(): void {
		console.log('RoundController onButton')
		this.rollDice()
	}

	private onDiceCountChange() {
		const diceCount = SettingManager.instance.settings.dice_num
		this.gridLayoutUtil.updateItemCount(diceCount)
		this.createDice()
	}

	/**
	 * 摇骰子
	 * @param playSound 是否播放音效
	 */
	private rollDice(playSound: boolean = true): void {
		if (this.roundState === RoundState.ROLLING) {
			return
		}
		let rollHandle = () => {
			this.roundState = RoundState.ROLLING
			this.createDice()

			if (playSound) {
				this.getComponent(AudioSource).play()
			}
			this.shakerController.setDragEnabled(false)
			AnimationUtils.createShakeAnimation(this.shakerContainer, RoundController.SHAKE_CONFIG, () => {
				this.roundState = RoundState.IDLE
				this.shakerController.setDragEnabled(true)
			})
			director.emit('DiceResut', this.diceList)
		}

		// 如果骰盅处于打开状态，则先关闭骰盅
		if (this.shakerController.getState() === ShakerState.OPEN) {
			this.shakerController.closeShaker()
			setTimeout(() => {
				rollHandle()
			}, 300)
		} else {
			rollHandle()
		}
	}

	private createDice() {
		// 随机创建骰子
		this.diceList = this.gridLayoutUtil.createLayout().map(node => node.getComponent(DiceController))
		// 设置随机点数
		this.diceList.forEach(dice => {
			dice.setDice(DiceUtil.rollDice())
		})
	}
}
